home *** CD-ROM | disk | FTP | other *** search
- [ Cracking Level-3 Your Second Key Generator ]
- ===============================================
-
- For this registration you'll need to set a different break point!
- This time you'll need to use GetWindowTextA, CString objects requires
- to use this for getting the entered text.
- This registration is to ease you into the next level, which it
- deals with indirect memory referencing. In C, it's call a pointer to
- a pointer. That's sort of like a CString, in which this registration
- routine uses for string storage. And it requires memory allocation, and
- reallocation when it needs to.
-
- Conventional pointer to a string. EAX = 0x00332211
- ADDRESS: EAX ---> (00332211)
- CONTENTS: "Some character string here!"
-
- Here is how a pointer to a pointer works. EAX = 0x00012345
- ADDRESS: EAX ---> (00012345) (00332211)
- CONTENTS: [00332211] ---> "Some character string here!"
-
- You should also know that what ever stored in the memory is in reverse
- order. Only when it gets transfer to the registers then it's in the
- correct order. For example, when EAX = 0x00012345, this is a pointer to
- a pointer to a memory. So after you do a "d eax", on the data window
- you should see a 4 bytes arrangement on the memory that reads "11 22 33 00".
- Now since EAX is a pointer to a pointer, the content of this memory
- should be the final poniter to the memory string. Then to view this
- memory string, do a "d 00332211", that will display the string in the
- data window. Instead of typing in "d 11223300", you typed in "d 00332211"
- that is becaue the 4 bytes are stored in reverse order!
-
- If you don't know what the heck a pointer to pointer is, don't worry.
- You don't really need to know it. The point of this registration is to show
- you another way that a program can obtain and store the user entered text.
- And cracking the registration should just be the same as what you did from
- the previous.
-
- See if you can trace through the entire code. And try to constantly
- display the memory as much as you can to spot the registration code.
-
- --------------------------------------------------------------------------
-
- :00401C2B BE45632781 mov esi, 81276345 ; initial value!!!
-
- :00401C7E E8670F0000 Call 00402BEA ; MFC42.GetWindowTextA
- :00401C83 8B6C2418 mov ebp, dword ptr [esp+18]
- :00401C87 8B55F8 mov edx, dword ptr [ebp-08]
- :00401C8A 83FA05 cmp edx, 00000005 ; make sure username is >= 5 char
- :00401C8D 7D11 jge 00401CA0
- :00401C8F 6A40 push 00000040
- :00401C91 6804514000 push 00405104
- :00401C96 68D8504000 push 004050D8
- :00401C9B E9E2000000 jmp 00401D82
-
- :00401CA0 33C0 xor eax, eax
- :00401CA2 3BD3 cmp edx, ebx
- :00401CA4 7E3C jle 00401CE2
- :00401CA6 B901000000 mov ecx, 00000001
- :00401CAB 33FF xor edi, edi
- :00401CAD 2BCD sub ecx, ebp
- :00401CAF 894C241C mov dword ptr [esp+1C], ecx
-
- ; this parts computes the secret key value!
- ; value is stored into ESI
- ; ESI has been previously initialized with 0x81276345
- :00401CB3 0FBE5C0500 movsx ebx, byte ptr [ebp+eax]
- :00401CB8 8D4C0500 lea ecx, dword ptr [ebp+eax]
- :00401CBC 03F3 add esi, ebx
- :00401CBE 8BD8 mov ebx, eax
- :00401CC0 C1E308 shl ebx, 08
- :00401CC3 33F3 xor esi, ebx
- :00401CC5 8B5C241C mov ebx, dword ptr [esp+1C]
- :00401CC9 03D9 add ebx, ecx
- :00401CCB 8BCF mov ecx, edi
- :00401CCD 0FAFF3 imul esi, ebx
- :00401CD0 F7D1 not ecx
- :00401CD2 0FAFF1 imul esi, ecx
- :00401CD5 40 inc eax
- :00401CD6 03FA add edi, edx
- :00401CD8 3BC2 cmp eax, edx
- :00401CDA 7CD7 jl 00401CB3
-
- :00401CDC 8B7C2420 mov edi, dword ptr [esp+20]
- :00401CE0 33DB xor ebx, ebx
-
- ; Call 00402BE4 works pretty much the same as wsprintf(), but it is the MFC
- ; version for working with CString objects. If you try to step into the call
- ; and trace what it is doing, you will be really confused. Just know that
- ; the parameter "%lu" tells it to convert an unsigned 32-bit value to a numeric
- ; string. Note that CString works like a dynamic allocated string.
- :00401CE2 56 push esi ; -> value to be printed
- :00401CE3 8D542414 lea edx, dword ptr [esp+14] ; gets a pointer
- :00401CE7 682C514000 push 0040512C ; -> "%lu"
- :00401CEC 52 push edx ; -> pointer to destination string
- :00401CED E8F20E0000 Call 00402BE4 ; -> print value (esi) to string
- :00401CF2 8B74241C mov esi, dword ptr [esp+1C] ; -> generated code
- :00401CF6 8B442420 mov eax, dword ptr [esp+20] ; -> password entered
- :00401CFA 83C40C add esp, 0000000C
-
- ; this part is the MFC version of compare string. It is a little bit different
- ; from lstrcmpA, but works pretty much the same. However it doesn't return any
- ; value. If the strings match up to the last byte, then they are equal!
- :00401CFD 8A10 mov dl, byte ptr [eax]
- :00401CFF 8ACA mov cl, dl
- :00401D01 3A16 cmp dl, byte ptr [esi]
- :00401D03 751C jne 00401D21
- :00401D05 3ACB cmp cl, bl
- :00401D07 7414 je 00401D1D
- :00401D09 8A5001 mov dl, byte ptr [eax+01]
- :00401D0C 8ACA mov cl, dl
- :00401D0E 3A5601 cmp dl, byte ptr [esi+01]
- :00401D11 750E jne 00401D21
- :00401D13 83C002 add eax, 00000002 ; eax = eax + 2
- :00401D16 83C602 add esi, 00000002 ; esi = esi + 2
- :00401D19 3ACB cmp cl, bl ; (cl - bl) test for zero
- :00401D1B 75E0 jne 00401CFD ; loop if not finish comparing
- :00401D1D 33C0 xor eax, eax
- :00401D1F EB05 jmp 00401D26
-
-
- Solution to the registration routine taken from my C++ source file.
- --------------------------------------------------------------------
- register DWORD sum = 0x81276345;
- register int i, slen;
- CString usrn = "", key = "", keystr = "";
-
- GetDlgItemText(IDC_USRN, usrn);
- GetDlgItemText(IDC_KEY, key);
- if ((slen = usrn.GetLength()) < 5)
- {
- MessageBox("User Name must have at least 5 characters.",
- "CrackMe", MB_OK | MB_ICONINFORMATION);
- return;
- }
- for (i = 0; i < slen; i++)
- {
- sum += usrn[i]; // Adding
- sum ^= (i << 8); // XORing
- sum *= ((i+1) * ~(slen * i)); // '~' means ones complement negation
- }
- keystr.Format("%lu", sum);
- if (key.Compare(keystr) == 0)
- {
- // correct registration code!
- }
- else
- {
- // incorrect registration code!
- }
-
- Sample of Key Generator
- -----------------------
- You need everything up to the point that says "keystr.Format("%lu", sum);"
- Display the string keystr[], and you'll have the registration code!
-